package tag

import (
	"github.com/jinzhu/gorm"
	"go-gin-api/app/model"
	grpctag "go-gin-api/app/proto/tag"
	"time"
)

type Tag struct {
	ID        int       `gorm:"column:id;primary_key" form:"id" json:"id"`
	Name      string    `form:"name" json:"name"`
	Status    int       `form:"status" json:"status"`
	CreatedAt time.Time `form:"created_at" json:"created_at"`
	UpdatedAt time.Time `form:"updated_at" json:"updated_at"`
}

type TagRepository interface {
	TagAdd(req *grpctag.TagRequest) (err error)
	TagDel(req *grpctag.TagDelRequest) (err error)
	TagUpdate(req *grpctag.TagUpdateRequest) (err error)
	TagList(req *grpctag.TagListRequest) (res []Tag, err error)
	TagInfo(req *grpctag.TagInfoRequest) (value Tag, err error)
	TagByName(name string) (value Tag)
	ExistsTagByName(name string,id int) (res bool)
}

type MysqlTag struct {

}

func NewMysqlTag() TagRepository {
	return &MysqlTag{

	}
}


func (t *MysqlTag) TagAdd(req *grpctag.TagRequest) (err error) {
	defer model.Db.Close()
	model.Db = model.Connect()
	value := Tag{
		ID:        0,
		Name:      req.Name,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}
	err = model.Db.Hander.Model(Tag{}).Create(&value).Error
	return
}

func (t *MysqlTag) TagDel(req *grpctag.TagDelRequest) (err error) {
	defer model.Db.Close()
	model.Db = model.Connect()
	var value Tag
	model.Db.Hander.Model(Tag{}).Where("id = ?", req.Id).First(&value)
	err = gorm.ErrRecordNotFound
	if value.ID > 0 {
		err = model.Db.Hander.Where("id = ?", req.Id).Delete(&value).Error
	}
	return
}

func (t *MysqlTag) TagByName(name string) (value Tag) {
	defer model.Db.Close()
	model.Db = model.Connect()
	model.Db.Hander.Model(Tag{}).Scopes(withTagName(name)).First(&value)
	return
}

func (t *MysqlTag) ExistsTagByName(name string,id int) (res bool) {
	defer model.Db.Close()
	model.Db = model.Connect()
	var count int
	categoryModel := model.Db.Hander.Model(Tag{}).Scopes(withTagName(name))
	if id > 0 {
		categoryModel = categoryModel.Where("id = ?",id)
	}
	categoryModel.Count(&count)
	if count > 0 {
		res = true
	}
	return
}

func (t *MysqlTag) TagUpdate(req *grpctag.TagUpdateRequest) (err error) {
	defer model.Db.Close()
	model.Db = model.Connect()
	var value Tag
	model.Db.Hander.Model(Tag{}).Where("id = ?", req.Id).First(&value)
	err = gorm.ErrRecordNotFound
	if value.ID > 0 {
		value.Name = req.Name
		err = model.Db.Hander.Where("id = ?", req.Id).Update(&value).Error
	}
	return
}

func (t *MysqlTag) TagList(req *grpctag.TagListRequest) (res []Tag, err error) {
	defer model.Db.Close()
	model.Db = model.Connect()
	err = model.Db.Hander.Model(Tag{}).
		Scopes(withStatus(req.Status), withTagLikeName(req.Name), withCreatedAt(req.CreatedAt)).
		Offset((req.Page-1) * req.Limit).
		Limit(req.Limit).
		Find(&res).Error
	return
}

func (t *MysqlTag) TagInfo(req *grpctag.TagInfoRequest) (value Tag, err error) {
	defer model.Db.Close()
	model.Db = model.Connect()
	err = model.Db.Hander.Model(Tag{}).Scopes(withTagID(req.Id)).First(&value).Error
	return
}

func withStatus(status int32) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		where := 1
		if status == 0 {
			where = 0
		}
		return db.Where("status = ?", where)
	}
}

func withTagLikeName(name string) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if name != "" {
			return db.Where("name like %?%", name)
		}
		return db
	}
}

func withTagName(name string) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if name != "" {
			return db.Where("name = ?", name)
		}
		return db
	}
}

func withCreatedAt(createdAt string) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if createdAt != "" {
			return db.Where("createdAt > ?", createdAt)
		}
		return db
	}
}

func withTagID(id int32) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if id > 0 {
			return db.Where("id = ? ", id)
		}
		return db
	}
}
